import time
import thread
import sys

from pydbg import *
from pydbg.defines import *

class egurFuzz(object):
	
	def __init__(self,timeout=0):
		
		self.exceptions = []
		self.timeout = timeout
		self.info = []
		
	def load(self, prog, args):

		self.dbg = pydbg()
		self.dbg.set_callback(EXCEPTION_ACCESS_VIOLATION,self.handler_access_exception_violation)
		self.dbg.load(prog,args)
		
	def run(self):
		
		if self.timeout != 0:
			thread.start_new_thread(self.watch, (self.dbg, ))
		self.dbg.debug_event_loop()
		
	def watch(self, dbg):
		
		time.sleep(self.timeout)
		if dbg.debugger_active:
			dbg.terminate_process()
	
	def print_info(self):
		
		for x in self.info:
			print x
			
	def dump_registers(self, dbg):
		
		reg = "EAX: 0x%08x\n" % dbg.context.Eax
		reg += "EBX: 0x%08x\n" % dbg.context.Ebx
		reg += "ECX: 0x%08x\n" % dbg.context.Ecx
		reg += "EDX: 0x%08x\n" % dbg.context.Edx
		reg += "ESI: 0x%08x\n" % dbg.context.Esi
		reg += "EDI: 0x%08x\n" % dbg.context.Edi
		reg += "EBP: 0x%08x\n" % dbg.context.Ebp
		reg += "ESP: 0x%08x\n" % dbg.context.Esp
		reg += "EIP: 0x%08x\n" % dbg.context.Eip
		return reg
	
	def handler_access_exception_violation(self, dbg):
		
		if dbg.context.Eip in self.exceptions:
			return DBG_EXCEPTION_NOT_HANDLED
		else:
			self.exceptions.append(dbg.context.Eip)
		print "\t[*] Crash logged!"
		self.info.append("**************************")
		self.info.append("Registers:")
		self.info.append(self.dump_registers(dbg))
		self.info.append("")
		self.info.append("Exception at address 0x%08x" % dbg.context.Eip)
		self.info.append("**************************")
		return DBG_CONTINUE
	
def main(prog,args):
	
	edbg = egurFuzz()
	edbg.timeout = 2
	edbg.load(prog,args)
	edbg.run()
	edbg.print_info()
	
def usage():
	
	print "Usage:",sys.argv[0],"<program> <arguments>"
	
if __name__ == "__main__":
	if len(sys.argv) != 3:
		usage()
	else:
		main(sys.argv[1], sys.argv[2])